using System;
using System.Collections.Generic;
using Oracle.ManagedDataAccess.Types;
using OracleInternal.Common;
using OracleInternal.ServiceObjects;

namespace OracleInternal.TTC.Accessors
{
	internal class TTCDateTimeAccessor : Accessor
	{
		internal const int ORACLE_CENTURY = 0;

		internal const int ORACLE_YEAR = 1;

		internal const int ORACLE_MONTH = 2;

		internal const int ORACLE_DAY = 3;

		internal const int ORACLE_HOUR = 4;

		internal const int ORACLE_MIN = 5;

		internal const int ORACLE_SEC = 6;

		internal const int ORACLE_NANO1 = 7;

		internal const int ORACLE_NANO2 = 8;

		internal const int ORACLE_NANO3 = 9;

		internal const int ORACLE_NANO4 = 10;

		internal const int ORACLE_TZ1 = 11;

		internal const int ORACLE_TZ2 = 12;

		internal const int MAX_DATE_LENGTH = 7;

		internal const int MAX_TIMESTAMP_LENGTH = 11;

		internal const int MAX_TIMESTAMP_LTZ_LENGTH = 11;

		internal const int MAX_TIMESTAMP_TZ_LENGTH = 13;

		internal const byte MinMinute = 0;

		internal const byte MinHour = 0;

		internal const byte MinDay = 1;

		internal const byte MinMonth = 1;

		internal const short MinYear = -4712;

		internal const byte MaxMinute = 59;

		internal const byte MaxHour = 23;

		internal const byte MaxDay = 31;

		internal const byte MaxMonth = 12;

		internal TTCDateTimeAccessor(ColumnDescribeInfo colMetaData, MarshallingEngine marshallingEngine, bool bForBind)
			: base(colMetaData, marshallingEngine, bForBind)
		{
			if (!bForBind)
			{
				InitForDataAccess(colMetaData.m_maxLength);
			}
		}

		internal override void InitForDataAccess(int max_len)
		{
			m_internalTypeMaxLength = m_colMetaData.m_maxLength;
			m_byteLength = m_internalTypeMaxLength;
		}

		internal override byte[] GetByteRepresentation(int currentRow)
		{
			byte[] array = null;
			int num = m_totalLengthOfData[currentRow];
			if (num > 0)
			{
				List<ArraySegment<byte>> list = m_RowDataSegments[currentRow];
				if (list != null)
				{
					array = ((!m_bForBind) ? new byte[num] : new byte[m_colMetaData.m_maxLength]);
					Accessor.CopyDataToUserBuffer(list, 0, array, 0, num);
				}
			}
			return array;
		}

		internal override byte[] GetByteRepresentation(DataUnmarshaller dataUnmarshaller, int currentRow, int columnIndex)
		{
			byte[] result = null;
			int length = 0;
			try
			{
				dataUnmarshaller.StartAccumulatingColumnData(currentRow, columnIndex, m_colDataSegments);
				dataUnmarshaller.UnmarshalCLR_ScanOnly(m_colMetaData.m_maxLength, ref length);
				if (length <= 0)
				{
					return result;
				}
				result = ((!m_bForBind) ? new byte[length] : new byte[m_colMetaData.m_maxLength]);
				Accessor.CopyDataToUserBuffer(m_colDataSegments, 0, result, 0, length);
				return result;
			}
			finally
			{
				m_colDataSegments.Clear();
				dataUnmarshaller.m_bAccumulateByteSegments = false;
				dataUnmarshaller.m_dataSegments = null;
			}
		}

		internal override DateTime GetDateTime(DataUnmarshaller dataUnmarshaller, int currentRow, int columnIndex, out byte[] byteRep)
		{
			int offset = 0;
			int length = 0;
			byteRep = null;
			try
			{
				dataUnmarshaller.StartAccumulatingColumnData(currentRow, columnIndex, m_colDataSegments);
				dataUnmarshaller.UnmarshalCLR_ScanOnly(m_colMetaData.m_maxLength, ref length);
				if (length > 0)
				{
					if (m_bForBind)
					{
						byteRep = new byte[m_colMetaData.m_maxLength];
					}
					else
					{
						byteRep = new byte[length];
					}
					Accessor.CopyDataToUserBuffer(m_colDataSegments, 0, byteRep, 0, length);
					return DateTimeConv.GetDateTime(byteRep, m_internalType, offset, length);
				}
				return default(DateTime);
			}
			finally
			{
				m_colDataSegments.Clear();
				dataUnmarshaller.m_bAccumulateByteSegments = false;
				dataUnmarshaller.m_dataSegments = null;
			}
		}

		internal override DateTime GetDateTime(int currentRow)
		{
			int offset = 0;
			int num = 0;
			num = m_totalLengthOfData[currentRow];
			DateTime result;
			if (num > 0)
			{
				List<ArraySegment<byte>> list = m_RowDataSegments[currentRow];
				if (list != null)
				{
					byte[] array = null;
					if (list.Count > 1)
					{
						array = ((!m_bForBind) ? new byte[num] : new byte[m_colMetaData.m_maxLength]);
						Accessor.CopyDataToUserBuffer(list, 0, array, 0, num);
					}
					else
					{
						array = list[0].Array;
						offset = list[0].Offset;
					}
					return DateTimeConv.GetDateTime(array, m_internalType, offset, num);
				}
				result = default(DateTime);
			}
			else
			{
				result = default(DateTime);
			}
			return result;
		}

		internal static void GetOracleDate(byte[] byteRep, DateTime paramVal)
		{
			byteRep[0] = (byte)(paramVal.Year / 100 + 100);
			byteRep[1] = (byte)(paramVal.Year % 100 + 100);
			byteRep[2] = (byte)paramVal.Month;
			byteRep[3] = (byte)paramVal.Day;
			byteRep[4] = (byte)(paramVal.Hour + 1);
			byteRep[5] = (byte)(paramVal.Minute + 1);
			byteRep[6] = (byte)(paramVal.Second + 1);
		}
	}
}
